From 7cd728a0ea3da812ea2b049cc79311a2349fd205 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 1 Mar 2020 18:50:15 +0100 Subject: [PATCH] gdk: Make gdk_drop_status() take preferred action This allows textview/text dnd to properly display a MOVE icon when in the widget the drag started from but a COPY icon otherwise. --- gdk/gdkdrop.c | 15 ++++++++++++--- gdk/gdkdrop.h | 3 ++- gdk/gdkdropprivate.h | 3 ++- gdk/wayland/gdkdrop-wayland.c | 20 +++++++------------- gdk/win32/gdkdrop-win32.c | 8 +++++--- gdk/x11/gdkdrop-x11.c | 23 +++++++++++++++-------- gtk/gtkdrop.c | 4 ++-- 7 files changed, 45 insertions(+), 31 deletions(-) diff --git a/gdk/gdkdrop.c b/gdk/gdkdrop.c index fd4169a29b..29c33f8ef5 100644 --- a/gdk/gdkdrop.c +++ b/gdk/gdkdrop.c @@ -75,7 +75,8 @@ G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkDrop, gdk_drop, G_TYPE_OBJECT) static void gdk_drop_default_status (GdkDrop *self, - GdkDragAction actions) + GdkDragAction actions, + GdkDragAction preferred) { } @@ -545,6 +546,8 @@ gdk_drop_get_drag (GdkDrop *self) * @self: a #GdkDrop * @actions: Supported actions of the destination, or 0 to indicate * that a drop will not be accepted + * @preferred: A unique action that's a member of @actions indicating the + * preferred action. * * Selects all actions that are potentially supported by the destination. * @@ -552,6 +555,9 @@ gdk_drop_get_drag (GdkDrop *self) * the ones provided by gdk_drop_get_actions(). Those actions may * change in the future, even depending on the actions you provide here. * + * The @preferred action is a hint to the drag'n'drop mechanism about which + * action to use when multiple actions are possible. + * * This function should be called by drag destinations in response to * %GDK_DRAG_ENTER or %GDK_DRAG_MOTION events. If the destination does * not yet know the exact actions it supports, it should set any possible @@ -559,7 +565,8 @@ gdk_drop_get_drag (GdkDrop *self) */ void gdk_drop_status (GdkDrop *self, - GdkDragAction actions) + GdkDragAction actions, + GdkDragAction preferred) { #ifndef G_DISABLE_CHECKS GdkDropPrivate *priv = gdk_drop_get_instance_private (self); @@ -567,8 +574,10 @@ gdk_drop_status (GdkDrop *self, g_return_if_fail (GDK_IS_DROP (self)); g_return_if_fail (priv->state != GDK_DROP_STATE_FINISHED); + g_return_if_fail (gdk_drag_action_is_unique (preferred)); + g_return_if_fail ((preferred & actions) == preferred); - GDK_DROP_GET_CLASS (self)->status (self, actions); + GDK_DROP_GET_CLASS (self)->status (self, actions, preferred); } /** diff --git a/gdk/gdkdrop.h b/gdk/gdkdrop.h index 6e29864293..c1990b1d67 100644 --- a/gdk/gdkdrop.h +++ b/gdk/gdkdrop.h @@ -54,7 +54,8 @@ GdkDrag * gdk_drop_get_drag (GdkDrop GDK_AVAILABLE_IN_ALL void gdk_drop_status (GdkDrop *self, - GdkDragAction actions); + GdkDragAction actions, + GdkDragAction preferred); GDK_AVAILABLE_IN_ALL void gdk_drop_finish (GdkDrop *self, GdkDragAction action); diff --git a/gdk/gdkdropprivate.h b/gdk/gdkdropprivate.h index 82b5e41945..6dbf8a0acf 100644 --- a/gdk/gdkdropprivate.h +++ b/gdk/gdkdropprivate.h @@ -40,7 +40,8 @@ struct _GdkDropClass { GObjectClass parent_class; void (* status) (GdkDrop *self, - GdkDragAction actions); + GdkDragAction actions, + GdkDragAction preferred); void (* finish) (GdkDrop *self, GdkDragAction action); diff --git a/gdk/wayland/gdkdrop-wayland.c b/gdk/wayland/gdkdrop-wayland.c index 2af4379077..5d72b3fcf6 100644 --- a/gdk/wayland/gdkdrop-wayland.c +++ b/gdk/wayland/gdkdrop-wayland.c @@ -122,7 +122,8 @@ gdk_wayland_drop_drop_set_status (GdkWaylandDrop *drop_wayland, static void gdk_wayland_drop_commit_status (GdkWaylandDrop *wayland_drop, - GdkDragAction actions) + GdkDragAction actions, + GdkDragAction preferred) { GdkDisplay *display; @@ -135,15 +136,7 @@ gdk_wayland_drop_commit_status (GdkWaylandDrop *wayland_drop, uint32_t preferred_action; dnd_actions = gdk_to_wl_actions (actions); - - if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) - preferred_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; - else if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) - preferred_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; - else if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) - preferred_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK; - else - preferred_action = 0; + preferred_action = gdk_to_wl_actions (preferred); wl_data_offer_set_actions (wayland_drop->offer, dnd_actions, preferred_action); } @@ -153,11 +146,12 @@ gdk_wayland_drop_commit_status (GdkWaylandDrop *wayland_drop, static void gdk_wayland_drop_status (GdkDrop *drop, - GdkDragAction actions) + GdkDragAction actions, + GdkDragAction preferred) { GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (drop); - gdk_wayland_drop_commit_status (wayland_drop, actions); + gdk_wayland_drop_commit_status (wayland_drop, actions, preferred); } static void @@ -170,7 +164,7 @@ gdk_wayland_drop_finish (GdkDrop *drop, if (action) { - gdk_wayland_drop_commit_status (wayland_drop, action); + gdk_wayland_drop_commit_status (wayland_drop, action, action); if (display_wayland->data_device_manager_version >= WL_DATA_OFFER_FINISH_SINCE_VERSION) diff --git a/gdk/win32/gdkdrop-win32.c b/gdk/win32/gdkdrop-win32.c index f7244f8f2e..ff6035dc4f 100644 --- a/gdk/win32/gdkdrop-win32.c +++ b/gdk/win32/gdkdrop-win32.c @@ -1059,7 +1059,8 @@ gdk_dropfiles_filter (GdkWin32Display *display, static void gdk_win32_drop_status (GdkDrop *drop, - GdkDragAction actions) + GdkDragAction actions, + GdkDragAction preferred) { GdkWin32Drop *drop_win32 = GDK_WIN32_DROP (drop); GdkDrag *drag; @@ -1067,10 +1068,11 @@ gdk_win32_drop_status (GdkDrop *drop, g_return_if_fail (drop != NULL); GDK_NOTE (DND, g_print ("gdk_win32_drop_status: %s\n" - " context=%p:{source_actions=%s}\n", + " context=%p:{source_actions=%s, preferred=%s}\n", _gdk_win32_drag_action_to_string (actions), drop, - _gdk_win32_drag_action_to_string (gdk_drop_get_actions (drop)))); + _gdk_win32_drag_action_to_string (gdk_drop_get_actions (drop)), + _gdk_win32_drag_action_to_string (preferred))); drop_win32->actions = actions; diff --git a/gdk/x11/gdkdrop-x11.c b/gdk/x11/gdkdrop-x11.c index d5cce6a6e1..6043f52b26 100644 --- a/gdk/x11/gdkdrop-x11.c +++ b/gdk/x11/gdkdrop-x11.c @@ -719,7 +719,8 @@ gdk_x11_drop_do_nothing (Window window, static void gdk_x11_drop_status (GdkDrop *drop, - GdkDragAction actions) + GdkDragAction actions, + GdkDragAction preferred) { GdkX11Drop *drop_x11 = GDK_X11_DROP (drop); GdkDragAction possible_actions, suggested_action; @@ -732,14 +733,20 @@ gdk_x11_drop_status (GdkDrop *drop, if (drop_x11->suggested_action != 0) suggested_action = drop_x11->suggested_action; - else if (possible_actions & GDK_ACTION_COPY) - suggested_action = GDK_ACTION_COPY; - else if (possible_actions & GDK_ACTION_MOVE) - suggested_action = GDK_ACTION_MOVE; - else if (possible_actions & GDK_ACTION_ASK) - suggested_action = GDK_ACTION_ASK; else - suggested_action = 0; + suggested_action = preferred & possible_actions; + + if (suggested_action == 0 && possible_actions != 0) + { + if (possible_actions & GDK_ACTION_COPY) + suggested_action = GDK_ACTION_COPY; + else if (possible_actions & GDK_ACTION_MOVE) + suggested_action = GDK_ACTION_MOVE; + else if (possible_actions & GDK_ACTION_ASK) + suggested_action = GDK_ACTION_ASK; + else + suggested_action = 0; + } xev.xclient.type = ClientMessage; xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "XdndStatus"); diff --git a/gtk/gtkdrop.c b/gtk/gtkdrop.c index 7c4c834dbc..eac5995b1f 100644 --- a/gtk/gtkdrop.c +++ b/gtk/gtkdrop.c @@ -86,7 +86,7 @@ gtk_drop_end_event (GdkDrop *drop) if (self->waiting) { - gdk_drop_status (drop, 0); + gdk_drop_status (drop, 0, 0); self->waiting = FALSE; } self->active = FALSE; @@ -106,7 +106,7 @@ gtk_drop_status (GdkDrop *drop, if (!self->waiting) return FALSE; - gdk_drop_status (drop, actions); + gdk_drop_status (drop, actions, preferred_action); self->waiting = FALSE; return TRUE; } -- 2.30.2